﻿// -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	SmartLib
//  File name:	MonadExts.cs
//  Developer:	Igor Solomatov
//  Created:	04.11.2012
// 
// -------------------- iSharePoint -------------------- //

using System;
using System.Collections.Generic;

namespace Smart
{
	public static class MonadExts
	{
		public static TResult With<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
			where TResult : class
			where TInput : class
		{
			return o != null ? evaluator(o) : null;
		}

		public static TResult With<TInput, TTemp, TResult>(this TInput o, Func<TInput, TTemp> evaluator0, Func<TTemp, TResult> evaluator1)
			where TResult : class
			where TTemp : class
			where TInput : class
		{
			var tmp = o != null ? evaluator0(o) : null;
			return tmp != null ? evaluator1(tmp) : null;
		}

		public static TResult With<TInput, TTemp0, TTemp1, TResult>(this TInput o, Func<TInput, TTemp0> evaluator0, Func<TTemp0, TTemp1> evaluator1, Func<TTemp1, TResult> evaluator2)
			where TResult : class
			where TTemp0 : class
			where TTemp1 : class
			where TInput : class
		{
			var tmp1 = o != null ? evaluator0(o) : null;
			var tmp2 = tmp1 != null ? evaluator1(tmp1) : null;
			return tmp2 != null ? evaluator2(tmp2) : null;
		}

		public static TResult With<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator, TResult failureValue)
			where TInput : class
		{
			return o != null ? evaluator(o) : failureValue;
		}


		public static TResult With<TInput, TTemp, TResult>(this TInput o, Func<TInput, TTemp> evaluator0, Func<TTemp, TResult> evaluator1, TResult failureValue)
			where TResult : class
			where TTemp : class
			where TInput : class
		{
			var tmp = o != null ? evaluator0(o) : null;
			return tmp != null ? evaluator1(tmp) : failureValue;
		}

		public static TResult With<TInput, TTemp0, TTemp1, TResult>(this TInput o, Func<TInput, TTemp0> evaluator0, Func<TTemp0, TTemp1> evaluator1, Func<TTemp1, TResult> evaluator2, TResult failureValue)
			where TResult : class
			where TTemp0 : class
			where TTemp1 : class
			where TInput : class
		{
			var tmp1 = o != null ? evaluator0(o) : null;
			var tmp2 = tmp1 != null ? evaluator1(tmp1) : null;
			return tmp2 != null ? evaluator2(tmp2) : failureValue;
		}

		public static TInput If<TInput>(this TInput o, Func<TInput, bool> evaluator)
			where TInput : class
		{
			return o != null ? (evaluator(o) ? o : null) : null;
		}

		public static TInput Unless<TInput>(this TInput o, Func<TInput, bool> evaluator)
			where TInput : class
		{
			return o != null ? (evaluator(o) ? null : o) : null;
		}

		public static TInput Do<TInput>(this TInput o, Action<TInput> action)
			where TInput : class
		{
			if (o == null) return null;
			action(o);
			return o;
		}

		public static TInput Or<TInput>(this TInput o, TInput defaultO)
			where TInput : class
		{
			return o ?? defaultO;
		}

		public static void Do<TInput>(this IEnumerable<TInput> o, Action<TInput> action)
		{
			if (o == null) return;
			foreach (var item in o) if (item != null) action(item);
		}
	}
}